package com.leetcode.concurrency;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Dennis Li
 * @date 2020/7/20 16:13
 */
public class FooBar {
    private int n;

    final Lock lock;

    final Condition fooCondition;
    final Condition barCondition;

    boolean fooFirst = true;

    public FooBar(int n) {
        lock = new ReentrantLock();
        fooCondition = lock.newCondition();
        barCondition = lock.newCondition();
        this.n = n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            if(!fooFirst) fooCondition.await();
            printFoo.run();
            fooFirst = !fooFirst;
            barCondition.signal();
            fooCondition.await();
            lock.unlock();
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            lock.lock();
            if(fooFirst) barCondition.await();
            printBar.run();
            fooFirst = !fooFirst;
            fooCondition.signal();
            barCondition.await();
            lock.unlock();
        }
    }
}
